/**
 *       Copyright (c) 2012 Lukas Zaruba
 *
 *   This file is part of Robot Playground.
 *
 *   Robot Playground is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   Robot Playground is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with Robot Playground. If not, see <http://www.gnu.org/licenses/>.
 */
package net.zarubsys.robotplayground.gui.session.providers;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;


/**
 * SystemObjectGUIProvidersHelper
 *
 * @author Lukas Zaruba, lukas.zaruba@gmail.com
 */
public class SystemObjectGUIProvidersHelper {
	
	private static final String EXT_POINT_ID = "net.zarubsys.robotplayground.gui.session.systemObjectGUIProviders";
	private static final Logger LOG = Logger.getLogger(SystemObjectGUIProvidersHelper.class);
	
	private final Map<SystemObjectGUIProviderClass, Map<String, ISystemObjectGUIProvider>> cache = new HashMap<SystemObjectGUIProviderClass, Map<String,ISystemObjectGUIProvider>>(); 
	
	private static final SystemObjectGUIProvidersHelper INSTANCE = new SystemObjectGUIProvidersHelper();
	
	private SystemObjectGUIProvidersHelper() {
		// to prevent instantiation
		init();
	}
	
	private void init() {
		IConfigurationElement[] cfgs = Platform.getExtensionRegistry().getConfigurationElementsFor(EXT_POINT_ID);
		for (IConfigurationElement cfg : cfgs) {
			try {
				ISystemObjectGUIProvider provider = (ISystemObjectGUIProvider) cfg.createExecutableExtension("class");
				IConfigurationElement[] children = cfg.getChildren("appliableIds");
				Set<String> appliableIds = new HashSet<>();
				for (IConfigurationElement appliableId : children) {
					appliableIds.add(appliableId.getAttribute("id"));
				}
				
				SystemObjectGUIProviderClass providerClass = provider.getProviderClass();
				Map<String, ISystemObjectGUIProvider> classCache = cache.get(providerClass);
				if (classCache == null) {
					classCache = new HashMap<>();
					cache.put(providerClass, classCache);
				}
				
				for (String id : appliableIds) {
					ISystemObjectGUIProvider registeredProvider = classCache.get(id);
					if (registeredProvider != null) {
						LOG.warn("There already is registered provider for class '" + providerClass + 
								"' and id '" + id + "' - class: " + registeredProvider.getClass().getName() + 
								"'. Skipping the new one (" + provider.getClass().getName() + " from bundle " + 
								cfg.getContributor().getName() + ")");
						continue;
					}
					classCache.put(id, provider);
				}
			} catch (CoreException e) {
				LOG.error("Error while creating executable extension to the ext. point '" + EXT_POINT_ID + "' from bundle '" + cfg.getContributor().getName() + "'! It will be skipped...", e);
			}
		}
	}

	public static SystemObjectGUIProvidersHelper getInstance() {
		return INSTANCE;
	}
	
	public ISystemObjectGUIProvider getProvider(SystemObjectGUIProviderClass klass, String id) {
		Map<String, ISystemObjectGUIProvider> classCache = cache.get(klass);
		if (classCache == null) return null;
		return classCache.get(id);
	}
	
	public Set<String> getAllIdsForClass(SystemObjectGUIProviderClass klass) {
		Map<String, ISystemObjectGUIProvider> classCache = cache.get(klass);
		if (classCache == null) return Collections.emptySet();
		return classCache.keySet();
	}
	
}

